Import Dataset and create working dataset:

#install.packages("plotly")
library(plotly)
package 㤼㸱plotly㤼㸲 was built under R version 4.0.4Loading required package: ggplot2
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: 㤼㸱plotly㤼㸲

The following object is masked from 㤼㸱package:ggplot2㤼㸲:

    last_plot

The following object is masked from 㤼㸱package:stats㤼㸲:

    filter

The following object is masked from 㤼㸱package:graphics㤼㸲:

    layout
library(reshape2)
package 㤼㸱reshape2㤼㸲 was built under R version 4.0.3
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages ------------------------------------------------------------------------------------------------------------------------------------ tidyverse 1.3.0 --
v tibble  3.0.3     v dplyr   1.0.2
v tidyr   1.1.2     v stringr 1.4.0
v readr   1.3.1     v forcats 0.5.1
v purrr   0.3.4     
package 㤼㸱forcats㤼㸲 was built under R version 4.0.4-- Conflicts --------------------------------------------------------------------------------------------------------------------------------------- tidyverse_conflicts() --
x dplyr::filter() masks plotly::filter(), stats::filter()
x dplyr::lag()    masks stats::lag()
games <- read.csv("../../data/vgsales.csv")
game_melt <- melt(data=games,id.vars = c("Rank","Name","Platform","Year","Genre","Publisher"),measure.vars=c("NA_Sales","EU_Sales","JP_Sales","Other_Sales","Global_Sales"))
game_melt$Year <- as.integer(game_melt$Year)
NAs introduced by coercion
colnames(game_melt)[7] <- "Region"
colnames(game_melt)[8] <- "Copies Sold"
head(game_melt)

Graph time baby!

#Number of Copies Sold
graph1 <- game_melt %>% 
    filter(Region == "NA_Sales") %>%
    group_by(Region,Year,Genre) %>%
    summarise("Copies Sold" = sum(`Copies Sold`)) %>% 
    ggplot() +
    aes(x=Year,
        y=`Copies Sold`,
        color = Genre) + 
    geom_line()+
    theme_bw()+
    theme(axis.text.x = element_text(angle = 90, hjust=0.95, vjust=0.2)) +
    ylab("Number of Copies Sold (in millions)")
`summarise()` regrouping output by 'Region', 'Year' (override with `.groups` argument)
    
ggplotly(graph1)
#Number Releases
graph2 <- game_melt %>% 
    filter(Region == "NA_Sales") %>%
    group_by(Region,Year,Genre) %>%
    count(Genre) %>%
    rename(`Number of Releases`="n")%>% 
    ggplot() +
    aes(x=Year,
        y=`Number of Releases`,
        fill = Genre) + 
    geom_bar(stat="identity")+
    theme_bw()+
    theme(panel.grid.major.x = element_blank())+
    theme(axis.text.x = element_text(angle = 90, hjust=0.95, vjust=0.2))+
    ylab("Number of Games Released")
ggplotly(graph2)
Removed 12 rows containing missing values (position_stack).
#Number of Platforms, Genres and Publishers with games > 100 copies sold 
graph3 <- game_melt %>% 
    filter(Region == "JP_Sales") %>%
    group_by(Year)%>%
    melt(id.vars=c("Year"),measure.vars=c("Genre","Platform","Publisher")) %>%
    rename(Category='variable') %>% 
    group_by(Year,Category) %>%
    unique() %>%
    count(Year,Category) %>%
    rename(`Counts of Genres, Publishers and Platforms`= n) %>% 
    ggplot() +
    aes(x=Year,
        y=`Counts of Genres, Publishers and Platforms`,
        fill = Category) + 
    geom_bar(stat="identity")+
    theme(axis.text.x = element_text(angle = 90, hjust=0.95, vjust=0.2))+
    ylab("Counts of Genres, Publishers and Platforms")
ggplotly(graph3)
Removed 3 rows containing missing values (position_stack).

x<-1
y<-list(x)
is.list(y)
[1] TRUE
testfxc1 <-function(reg,plat,gen,pub,years) {
         # Input: List of Regions, Platforms, Genres, Publishers, Min and Max Year
         # Output: Graph
         #
         # Create subset based on filters 
         # Pass to graph
         # Output graph
        if ("Global_Sales" %in% reg){
            filter_region = list("Global_Sales")
        } else {
            filter_region = reg
        }
         if ("all" %in% plat){
             filter_plat = unique(game_melt$Platform)
         } else {
             filter_plat = plat
         }
         if ("all" %in% gen){
             filter_gen = unique(game_melt$Genre)
         } else {
             filter_gen = gen
         }
         if ("all" %in% pub){
             filter_pub = unique(game_melt$Publisher)
         } else {
             filter_pub = pub
         }
         min_year = years[1]
         max_year = years[2]
         
         graph1 <- game_melt[,3:8] %>% 
             subset(Region %in% filter_region & Platform %in% filter_plat & Genre %in% filter_gen & Publisher %in% filter_pub & Year >= min_year & Year <= max_year) %>%
             group_by(Year,Genre) %>%
             summarise("Copies Sold" = sum(`Copies Sold`)) %>% 
             ggplot() +
             aes(x=as.factor(Year),
                 y=`Copies Sold`,
                 fill = Genre) + 
             geom_bar(stat="identity")+
             theme(axis.text.x = element_text(angle = 90, hjust=0.95, vjust=0.2)) +
             ylab("Total Game Copies Sold (in millions)")
         
         return (ggplotly(graph1))
}

testfxc2 <-function(reg,plat,gen,pub,years) {
        # Input: List of Regions, Platforms, Genres, Publishers, Min and Max Year
        # Output: Graph
        #
        # Create subset based on filters 
        # Pass to graph
        # Output graph
        if ("Global_Sales" %in% reg){
            filter_region = list("Global_Sales")
        } else {
            filter_region = reg
        }
        if ("all" %in% plat){
            filter_plat = unique(game_melt$Platform)
        } else {
            filter_plat = plat
        }
        if ("all" %in% gen){
            filter_gen = unique(game_melt$Genre)
        } else {
            filter_gen = gen
        }
        if ("all" %in% pub){
            filter_pub = unique(game_melt$Publisher)
        } else {
            filter_pub = pub
        }
        min_year = years[1]
        max_year = years[2]
        
        graph2 <- game_melt[,3:8] %>% 
            subset(Region %in% filter_region & Platform %in% filter_plat & Genre %in% filter_gen & Publisher %in% filter_pub & Year >= min_year & Year <= max_year) %>%
            group_by(Year,Genre) %>%
            count(Year,Genre) %>%
            rename(`Number of Releases`="n") %>% 
            ggplot() +
            aes(x=as.factor(Year),
                y=`Number of Releases`,
                fill = Genre) + 
            geom_bar(stat="identity")+
            theme_bw()+
            theme(axis.text.x = element_text(angle = 90, hjust=0.95, vjust=0.2))+
            ylab("Number of Games Released")

        return (ggplotly(graph2))
    }
filtered_game_melt %>%
    group_by(Year,Genre) %>%
    summarise("Copies Sold" = sum(`Copies Sold`)) %>%
    ggplot()+
    aes(x=Year,
        y=`Copies Sold`,
        color=Genre)+
    geom_line()+
    theme_bw() +
    theme(legend.title=element_blank()) +
    theme(panel.grid.major.x = element_blank())
Error in group_by(., Year, Genre) : object 'filtered_game_melt' not found
filter_region = list("JP_Sales")
filter_plat = unique(game_melt$Platform)
filter_gen = unique(game_melt$Genre)
filter_pub = unique(game_melt$Publisher)
min_year = 1980
max_year = 2017

 filtered_game_melt <- game_melt[,3:8] %>% 
            subset(Region %in% filter_region & Platform %in% filter_plat & Genre %in% filter_gen & Publisher %in% filter_pub & Year >= min_year & Year <= max_year)

graph1 <-  filtered_game_melt %>%
    group_by(Year,Genre) %>%
    summarise("Copies Sold" = sum(`Copies Sold`)) %>% 
    ggplot() +
    aes(x=Year,
        y=`Copies Sold`,
        color = Genre,
        group = 1,
        text = paste("Year: ",Year,
                     "<br>Copies Sold: ",`Copies Sold`,
                     "<br>Genre: ", Genre)) + 
    geom_line()+
    theme_bw() +
    theme(legend.title=element_blank()) +
    theme(panel.grid.major.x = element_blank()) + 
    theme(axis.text.x = element_text(angle = 90, hjust=0.95, vjust=0.2)) +
    #scale_fill_manual(values=c("#999999", "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")) +
    ylab("Number of Copies Sold (in millions)")+
    xlab("Year")
`summarise()` regrouping output by 'Year' (override with `.groups` argument)
ggplotly(graph1,tooltip="text")

NA
filter_region = list("JP_Sales")
filter_plat = list("XOne")
#filter_plat = unique(game_melt$Platform)
filter_gen = unique(game_melt$Genre)
filter_pub = unique(game_melt$Publisher)
min_year = 1980
max_year = 1990

filtered_game_melt <- game_melt[,3:8] %>% 
    subset(Region %in% filter_region & Platform %in% filter_plat & Genre %in% filter_gen & Publisher %in% filter_pub & Year >= min_year & Year <= max_year)
filtered_game_melt
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KSW1wb3J0IERhdGFzZXQgYW5kIGNyZWF0ZSB3b3JraW5nIGRhdGFzZXQ6DQpgYGB7cn0NCiNpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpnYW1lcyA8LSByZWFkLmNzdigiLi4vLi4vZGF0YS92Z3NhbGVzLmNzdiIpDQpnYW1lX21lbHQgPC0gbWVsdChkYXRhPWdhbWVzLGlkLnZhcnMgPSBjKCJSYW5rIiwiTmFtZSIsIlBsYXRmb3JtIiwiWWVhciIsIkdlbnJlIiwiUHVibGlzaGVyIiksbWVhc3VyZS52YXJzPWMoIk5BX1NhbGVzIiwiRVVfU2FsZXMiLCJKUF9TYWxlcyIsIk90aGVyX1NhbGVzIiwiR2xvYmFsX1NhbGVzIikpDQpnYW1lX21lbHQkWWVhciA8LSBhcy5pbnRlZ2VyKGdhbWVfbWVsdCRZZWFyKQ0KY29sbmFtZXMoZ2FtZV9tZWx0KVs3XSA8LSAiUmVnaW9uIg0KY29sbmFtZXMoZ2FtZV9tZWx0KVs4XSA8LSAiQ29waWVzIFNvbGQiDQpoZWFkKGdhbWVfbWVsdCkNCmBgYA0KR3JhcGggdGltZSBiYWJ5IQ0KYGBge3J9DQojTnVtYmVyIG9mIENvcGllcyBTb2xkDQpncmFwaDEgPC0gZ2FtZV9tZWx0ICU+JSANCiAgICBmaWx0ZXIoUmVnaW9uID09ICJOQV9TYWxlcyIpICU+JQ0KICAgIGdyb3VwX2J5KFJlZ2lvbixZZWFyLEdlbnJlKSAlPiUNCiAgICBzdW1tYXJpc2UoIkNvcGllcyBTb2xkIiA9IHN1bShgQ29waWVzIFNvbGRgKSkgJT4lIA0KICAgIGdncGxvdCgpICsNCiAgICBhZXMoeD1ZZWFyLA0KICAgICAgICB5PWBDb3BpZXMgU29sZGAsDQogICAgICAgIGNvbG9yID0gR2VucmUpICsgDQogICAgZ2VvbV9saW5lKCkrDQogICAgdGhlbWVfYncoKSsNCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdD0wLjk1LCB2anVzdD0wLjIpKSArDQogICAgeWxhYigiTnVtYmVyIG9mIENvcGllcyBTb2xkIChpbiBtaWxsaW9ucykiKQ0KICAgIA0KZ2dwbG90bHkoZ3JhcGgxKQ0KYGBgDQoNCmBgYHtyfQ0KI051bWJlciBSZWxlYXNlcw0KZ3JhcGgyIDwtIGdhbWVfbWVsdCAlPiUgDQogICAgZmlsdGVyKFJlZ2lvbiA9PSAiTkFfU2FsZXMiKSAlPiUNCiAgICBncm91cF9ieShSZWdpb24sWWVhcixHZW5yZSkgJT4lDQogICAgY291bnQoR2VucmUpICU+JQ0KICAgIHJlbmFtZShgTnVtYmVyIG9mIFJlbGVhc2VzYD0ibiIpJT4lIA0KICAgIGdncGxvdCgpICsNCiAgICBhZXMoeD1ZZWFyLA0KICAgICAgICB5PWBOdW1iZXIgb2YgUmVsZWFzZXNgLA0KICAgICAgICBmaWxsID0gR2VucmUpICsgDQogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsNCiAgICB0aGVtZV9idygpKw0KICAgIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSkrDQogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3Q9MC45NSwgdmp1c3Q9MC4yKSkrDQogICAgeWxhYigiTnVtYmVyIG9mIEdhbWVzIFJlbGVhc2VkIikNCmdncGxvdGx5KGdyYXBoMikNCmBgYA0KYGBge3J9DQojTnVtYmVyIG9mIFBsYXRmb3JtcywgR2VucmVzIGFuZCBQdWJsaXNoZXJzIHdpdGggZ2FtZXMgPiAxMDAgY29waWVzIHNvbGQgDQpncmFwaDMgPC0gZ2FtZV9tZWx0ICU+JSANCiAgICBmaWx0ZXIoUmVnaW9uID09ICJKUF9TYWxlcyIpICU+JQ0KICAgIGdyb3VwX2J5KFllYXIpJT4lDQogICAgbWVsdChpZC52YXJzPWMoIlllYXIiKSxtZWFzdXJlLnZhcnM9YygiR2VucmUiLCJQbGF0Zm9ybSIsIlB1Ymxpc2hlciIpKSAlPiUNCiAgICByZW5hbWUoQ2F0ZWdvcnk9J3ZhcmlhYmxlJykgJT4lIA0KICAgIGdyb3VwX2J5KFllYXIsQ2F0ZWdvcnkpICU+JQ0KICAgIHVuaXF1ZSgpICU+JQ0KICAgIGNvdW50KFllYXIsQ2F0ZWdvcnkpICU+JQ0KICAgIHJlbmFtZShgQ291bnRzIG9mIEdlbnJlcywgUHVibGlzaGVycyBhbmQgUGxhdGZvcm1zYD0gbikgJT4lIA0KICAgIGdncGxvdCgpICsNCiAgICBhZXMoeD1ZZWFyLA0KICAgICAgICB5PWBDb3VudHMgb2YgR2VucmVzLCBQdWJsaXNoZXJzIGFuZCBQbGF0Zm9ybXNgLA0KICAgICAgICBmaWxsID0gQ2F0ZWdvcnkpICsgDQogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsNCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdD0wLjk1LCB2anVzdD0wLjIpKSsNCiAgICB5bGFiKCJDb3VudHMgb2YgR2VucmVzLCBQdWJsaXNoZXJzIGFuZCBQbGF0Zm9ybXMiKQ0KZ2dwbG90bHkoZ3JhcGgzKQ0KeDwtMQ0KeTwtbGlzdCh4KQ0KaXMubGlzdCh5KQ0KYGBgDQoNCmBgYHtyfQ0KdGVzdGZ4YzEgPC1mdW5jdGlvbihyZWcscGxhdCxnZW4scHViLHllYXJzKSB7DQogICAgICAgICAjIElucHV0OiBMaXN0IG9mIFJlZ2lvbnMsIFBsYXRmb3JtcywgR2VucmVzLCBQdWJsaXNoZXJzLCBNaW4gYW5kIE1heCBZZWFyDQogICAgICAgICAjIE91dHB1dDogR3JhcGgNCiAgICAgICAgICMNCiAgICAgICAgICMgQ3JlYXRlIHN1YnNldCBiYXNlZCBvbiBmaWx0ZXJzIA0KICAgICAgICAgIyBQYXNzIHRvIGdyYXBoDQogICAgICAgICAjIE91dHB1dCBncmFwaA0KICAgICAgICBpZiAoIkdsb2JhbF9TYWxlcyIgJWluJSByZWcpew0KICAgICAgICAgICAgZmlsdGVyX3JlZ2lvbiA9IGxpc3QoIkdsb2JhbF9TYWxlcyIpDQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICBmaWx0ZXJfcmVnaW9uID0gcmVnDQogICAgICAgIH0NCiAgICAgICAgIGlmICgiYWxsIiAlaW4lIHBsYXQpew0KICAgICAgICAgICAgIGZpbHRlcl9wbGF0ID0gdW5pcXVlKGdhbWVfbWVsdCRQbGF0Zm9ybSkNCiAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgZmlsdGVyX3BsYXQgPSBwbGF0DQogICAgICAgICB9DQogICAgICAgICBpZiAoImFsbCIgJWluJSBnZW4pew0KICAgICAgICAgICAgIGZpbHRlcl9nZW4gPSB1bmlxdWUoZ2FtZV9tZWx0JEdlbnJlKQ0KICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICBmaWx0ZXJfZ2VuID0gZ2VuDQogICAgICAgICB9DQogICAgICAgICBpZiAoImFsbCIgJWluJSBwdWIpew0KICAgICAgICAgICAgIGZpbHRlcl9wdWIgPSB1bmlxdWUoZ2FtZV9tZWx0JFB1Ymxpc2hlcikNCiAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgZmlsdGVyX3B1YiA9IHB1Yg0KICAgICAgICAgfQ0KICAgICAgICAgbWluX3llYXIgPSB5ZWFyc1sxXQ0KICAgICAgICAgbWF4X3llYXIgPSB5ZWFyc1syXQ0KICAgICAgICAgDQogICAgICAgICBncmFwaDEgPC0gZ2FtZV9tZWx0WywzOjhdICU+JSANCiAgICAgICAgICAgICBzdWJzZXQoUmVnaW9uICVpbiUgZmlsdGVyX3JlZ2lvbiAmIFBsYXRmb3JtICVpbiUgZmlsdGVyX3BsYXQgJiBHZW5yZSAlaW4lIGZpbHRlcl9nZW4gJiBQdWJsaXNoZXIgJWluJSBmaWx0ZXJfcHViICYgWWVhciA+PSBtaW5feWVhciAmIFllYXIgPD0gbWF4X3llYXIpICU+JQ0KICAgICAgICAgICAgIGdyb3VwX2J5KFllYXIsR2VucmUpICU+JQ0KICAgICAgICAgICAgIHN1bW1hcmlzZSgiQ29waWVzIFNvbGQiID0gc3VtKGBDb3BpZXMgU29sZGApKSAlPiUgDQogICAgICAgICAgICAgZ2dwbG90KCkgKw0KICAgICAgICAgICAgIGFlcyh4PWFzLmZhY3RvcihZZWFyKSwNCiAgICAgICAgICAgICAgICAgeT1gQ29waWVzIFNvbGRgLA0KICAgICAgICAgICAgICAgICBmaWxsID0gR2VucmUpICsgDQogICAgICAgICAgICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsNCiAgICAgICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdD0wLjk1LCB2anVzdD0wLjIpKSArDQogICAgICAgICAgICAgeWxhYigiVG90YWwgR2FtZSBDb3BpZXMgU29sZCAoaW4gbWlsbGlvbnMpIikNCiAgICAgICAgIA0KICAgICAgICAgcmV0dXJuIChnZ3Bsb3RseShncmFwaDEpKQ0KfQ0KDQp0ZXN0ZnhjMiA8LWZ1bmN0aW9uKHJlZyxwbGF0LGdlbixwdWIseWVhcnMpIHsNCiAgICAgICAgIyBJbnB1dDogTGlzdCBvZiBSZWdpb25zLCBQbGF0Zm9ybXMsIEdlbnJlcywgUHVibGlzaGVycywgTWluIGFuZCBNYXggWWVhcg0KICAgICAgICAjIE91dHB1dDogR3JhcGgNCiAgICAgICAgIw0KICAgICAgICAjIENyZWF0ZSBzdWJzZXQgYmFzZWQgb24gZmlsdGVycyANCiAgICAgICAgIyBQYXNzIHRvIGdyYXBoDQogICAgICAgICMgT3V0cHV0IGdyYXBoDQogICAgICAgIGlmICgiR2xvYmFsX1NhbGVzIiAlaW4lIHJlZyl7DQogICAgICAgICAgICBmaWx0ZXJfcmVnaW9uID0gbGlzdCgiR2xvYmFsX1NhbGVzIikNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIGZpbHRlcl9yZWdpb24gPSByZWcNCiAgICAgICAgfQ0KICAgICAgICBpZiAoImFsbCIgJWluJSBwbGF0KXsNCiAgICAgICAgICAgIGZpbHRlcl9wbGF0ID0gdW5pcXVlKGdhbWVfbWVsdCRQbGF0Zm9ybSkNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIGZpbHRlcl9wbGF0ID0gcGxhdA0KICAgICAgICB9DQogICAgICAgIGlmICgiYWxsIiAlaW4lIGdlbil7DQogICAgICAgICAgICBmaWx0ZXJfZ2VuID0gdW5pcXVlKGdhbWVfbWVsdCRHZW5yZSkNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIGZpbHRlcl9nZW4gPSBnZW4NCiAgICAgICAgfQ0KICAgICAgICBpZiAoImFsbCIgJWluJSBwdWIpew0KICAgICAgICAgICAgZmlsdGVyX3B1YiA9IHVuaXF1ZShnYW1lX21lbHQkUHVibGlzaGVyKQ0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgZmlsdGVyX3B1YiA9IHB1Yg0KICAgICAgICB9DQogICAgICAgIG1pbl95ZWFyID0geWVhcnNbMV0NCiAgICAgICAgbWF4X3llYXIgPSB5ZWFyc1syXQ0KICAgICAgICANCiAgICAgICAgZ3JhcGgyIDwtIGdhbWVfbWVsdFssMzo4XSAlPiUgDQogICAgICAgICAgICBzdWJzZXQoUmVnaW9uICVpbiUgZmlsdGVyX3JlZ2lvbiAmIFBsYXRmb3JtICVpbiUgZmlsdGVyX3BsYXQgJiBHZW5yZSAlaW4lIGZpbHRlcl9nZW4gJiBQdWJsaXNoZXIgJWluJSBmaWx0ZXJfcHViICYgWWVhciA+PSBtaW5feWVhciAmIFllYXIgPD0gbWF4X3llYXIpICU+JQ0KICAgICAgICAgICAgZ3JvdXBfYnkoWWVhcixHZW5yZSkgJT4lDQogICAgICAgICAgICBjb3VudChZZWFyLEdlbnJlKSAlPiUNCiAgICAgICAgICAgIHJlbmFtZShgTnVtYmVyIG9mIFJlbGVhc2VzYD0ibiIpICU+JSANCiAgICAgICAgICAgIGdncGxvdCgpICsNCiAgICAgICAgICAgIGFlcyh4PWFzLmZhY3RvcihZZWFyKSwNCiAgICAgICAgICAgICAgICB5PWBOdW1iZXIgb2YgUmVsZWFzZXNgLA0KICAgICAgICAgICAgICAgIGZpbGwgPSBHZW5yZSkgKyANCiAgICAgICAgICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikrDQogICAgICAgICAgICB0aGVtZV9idygpKw0KICAgICAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3Q9MC45NSwgdmp1c3Q9MC4yKSkrDQogICAgICAgICAgICB5bGFiKCJOdW1iZXIgb2YgR2FtZXMgUmVsZWFzZWQiKQ0KDQogICAgICAgIHJldHVybiAoZ2dwbG90bHkoZ3JhcGgyKSkNCiAgICB9DQpgYGANCg0KYGBge3J9DQpmaWx0ZXJlZF9nYW1lX21lbHQgJT4lDQogICAgZ3JvdXBfYnkoWWVhcixHZW5yZSkgJT4lDQogICAgc3VtbWFyaXNlKCJDb3BpZXMgU29sZCIgPSBzdW0oYENvcGllcyBTb2xkYCkpICU+JQ0KICAgIGdncGxvdCgpKw0KICAgIGFlcyh4PVllYXIsDQogICAgICAgIHk9YENvcGllcyBTb2xkYCwNCiAgICAgICAgY29sb3I9R2VucmUpKw0KICAgIGdlb21fbGluZSgpKw0KICAgIHRoZW1lX2J3KCkgKw0KICAgIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsNCiAgICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkpDQpgYGANCg0KYGBge3J9DQpmaWx0ZXJfcmVnaW9uID0gbGlzdCgiSlBfU2FsZXMiKQ0KZmlsdGVyX3BsYXQgPSB1bmlxdWUoZ2FtZV9tZWx0JFBsYXRmb3JtKQ0KZmlsdGVyX2dlbiA9IHVuaXF1ZShnYW1lX21lbHQkR2VucmUpDQpmaWx0ZXJfcHViID0gdW5pcXVlKGdhbWVfbWVsdCRQdWJsaXNoZXIpDQptaW5feWVhciA9IDE5ODANCm1heF95ZWFyID0gMjAxNw0KDQogZmlsdGVyZWRfZ2FtZV9tZWx0IDwtIGdhbWVfbWVsdFssMzo4XSAlPiUgDQogICAgICAgICAgICBzdWJzZXQoUmVnaW9uICVpbiUgZmlsdGVyX3JlZ2lvbiAmIFBsYXRmb3JtICVpbiUgZmlsdGVyX3BsYXQgJiBHZW5yZSAlaW4lIGZpbHRlcl9nZW4gJiBQdWJsaXNoZXIgJWluJSBmaWx0ZXJfcHViICYgWWVhciA+PSBtaW5feWVhciAmIFllYXIgPD0gbWF4X3llYXIpDQoNCmdyYXBoMSA8LSAgZmlsdGVyZWRfZ2FtZV9tZWx0ICU+JQ0KICAgIGdyb3VwX2J5KFllYXIsR2VucmUpICU+JQ0KICAgIHN1bW1hcmlzZSgiQ29waWVzIFNvbGQiID0gc3VtKGBDb3BpZXMgU29sZGApKSAlPiUgDQogICAgZ2dwbG90KCkgKw0KICAgIGFlcyh4PVllYXIsDQogICAgICAgIHk9YENvcGllcyBTb2xkYCwNCiAgICAgICAgY29sb3IgPSBHZW5yZSwNCiAgICAgICAgZ3JvdXAgPSAxLA0KICAgICAgICB0ZXh0ID0gcGFzdGUoIlllYXI6ICIsWWVhciwNCiAgICAgICAgICAgICAgICAgICAgICI8YnI+Q29waWVzIFNvbGQ6ICIsYENvcGllcyBTb2xkYCwNCiAgICAgICAgICAgICAgICAgICAgICI8YnI+R2VucmU6ICIsIEdlbnJlKSkgKyANCiAgICBnZW9tX2xpbmUoKSsNCiAgICB0aGVtZV9idygpICsNCiAgICB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArDQogICAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKSArIA0KICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0PTAuOTUsIHZqdXN0PTAuMikpICsNCiAgICAjc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiM5OTk5OTkiLCAiI0U2OUYwMCIsICIjNTZCNEU5IiwgIiMwMDlFNzMiLCAiI0YwRTQ0MiIsICIjMDA3MkIyIiwgIiNENTVFMDAiLCAiI0NDNzlBNyIpKSArDQogICAgeWxhYigiTnVtYmVyIG9mIENvcGllcyBTb2xkIChpbiBtaWxsaW9ucykiKSsNCiAgICB4bGFiKCJZZWFyIikNCmdncGxvdGx5KGdyYXBoMSx0b29sdGlwPSJ0ZXh0IikNCg0KYGBgDQoNCmBgYHtyfQ0KZmlsdGVyX3JlZ2lvbiA9IGxpc3QoIkpQX1NhbGVzIikNCmZpbHRlcl9wbGF0ID0gbGlzdCgiWE9uZSIpDQpmaWx0ZXJfZ2VuID0gdW5pcXVlKGdhbWVfbWVsdCRHZW5yZSkNCmZpbHRlcl9wdWIgPSB1bmlxdWUoZ2FtZV9tZWx0JFB1Ymxpc2hlcikNCm1pbl95ZWFyID0gMTk4MA0KbWF4X3llYXIgPSAxOTkwDQoNCmZpbHRlcmVkX2dhbWVfbWVsdCA8LSBnYW1lX21lbHRbLDM6OF0gJT4lIA0KICAgIHN1YnNldChSZWdpb24gJWluJSBmaWx0ZXJfcmVnaW9uICYgUGxhdGZvcm0gJWluJSBmaWx0ZXJfcGxhdCAmIEdlbnJlICVpbiUgZmlsdGVyX2dlbiAmIFB1Ymxpc2hlciAlaW4lIGZpbHRlcl9wdWIgJiBZZWFyID49IG1pbl95ZWFyICYgWWVhciA8PSBtYXhfeWVhcikNCmZpbHRlcmVkX2dhbWVfbWVsdA0KYGBgDQoNCg0KDQo=